package everything;

public abstract class Agent {



	protected int _xLocation;
	protected int _yLocation;
	protected String _orientation;
	protected boolean _onIce;
	protected boolean _isGhost;
	protected int _score;
	protected WorldMap _map;
	protected String _name;
	protected String _color;
	protected String _type;
	protected int _bullets;
	protected int _id;

	protected Agent(){

	}

	public Agent(String name, String color, int x, int y, WorldMap map, int id) {
		_xLocation = x;
		_yLocation = y;
		_orientation = "NORTH";
		_name = name;
		_color = color;
		_map = map;
		_bullets = map.getBullets();
		_onIce = false;
		_score = 0;
		_id = id;
	}

	public int getId() {
		return _id;
	}
	
	public String getName() {
		return _name;
	}

	public String getColor() {
		return _color;
	}

	public String getDispOrientation() {
		return _orientation;
	}

	public void setOrientation(String orientation) {
		_score--;
		_orientation = orientation;
		_map.turnAgent(this, orientation);
	}

	public String getSlidingDirection(){
		if (!_onIce) return null;
		else return _orientation;
	}


	public int getX(){
		return _xLocation;
	}
	public int getY(){
		return _yLocation;
	}


	protected void move(String direction){
		// when on ice, unable to turn
		boolean shoot = "Fire".equalsIgnoreCase(direction);
		if (shoot) _map.tryToKill(this);
		if (!_onIce && !shoot){	//not on ice and not shooting , turns the agent
			_orientation = direction;
			_map.turnAgent(this, _orientation);
		} else if (!shoot) { //not shooting , attempt to break from ice slipping
			double random = Math.random();
			if (random < _map.getNotSlippingP()){ //managed to stop slipping
				_orientation = direction;
				_map.turnAgent(this, _orientation);
			}
		}
		int oldX = _xLocation;
		int oldY = _yLocation;
		//moves the agent according to orientation, in case he is on ice or asked to move (!shoot)
		if (_onIce || !shoot){
			if (_orientation.equalsIgnoreCase("North") && ! _map.isMovementBlocked(_xLocation-1, _yLocation)){
				_xLocation--;
				_map.moveAgent(this, _orientation);
				_map.restore(oldX,oldY);
			} else if (_orientation.equalsIgnoreCase("East") && !_map.isMovementBlocked(_xLocation, _yLocation+1)){
				_yLocation++;
				_map.moveAgent(this, _orientation);
				_map.restore(oldX,oldY);
			} else if (_orientation.equalsIgnoreCase("South") && !_map.isMovementBlocked(_xLocation+1,_yLocation)){
				_xLocation++;
				_map.moveAgent(this, _orientation);
				_map.restore(oldX,oldY);
			} else if (_orientation.equalsIgnoreCase("West") && !_map.isMovementBlocked(_xLocation, _yLocation-1)){
				_yLocation--;
				_map.moveAgent(this, _orientation);
				_map.restore(oldX,oldY);
			}
		}
		// found flag
		if (_map.brickStatus(_xLocation, _yLocation) == WorldMap.FLAG && !_isGhost){
			// if _map.isFlag(_xLocation, _yLocation)
			_score += _map.getFlagValue(_xLocation, _yLocation);
			_map.takeFlag(_xLocation, _yLocation,_id);

		}
		//checks if the agent landed on ice
		if (_map.isIce(_xLocation, _yLocation)){
			_onIce = true;
			// if near wall, agent stops and is able to turn
			if (_orientation.equalsIgnoreCase("North")){
				if(_map.isMovementBlocked(_xLocation - 1, _yLocation)){
					_onIce = false;
				}
			} else if (_orientation.equalsIgnoreCase("East")){
				if(_map.isMovementBlocked(_xLocation , _yLocation + 1)){
					_onIce = false;
				}
			} else if (_orientation.equalsIgnoreCase("South")){
				if(_map.isMovementBlocked(_xLocation + 1, _yLocation)){
					_onIce = false;
				}
			} else if (_orientation.equalsIgnoreCase("West")){
				if(_map.isMovementBlocked(_xLocation , _yLocation - 1)){
					_onIce = false;
				}
			} else {	//orientation = shoot
				_onIce = false;
			}
		} else {
			_onIce = false;
		}
		_map.updateScore(this);
	}

	public abstract void makeMove();

	public boolean isGhost() {
		return _isGhost;
	}

	public void die(){
		_isGhost = true;
	}

	public int getScore() {
		return _score;
	}

	public boolean hasBullets(){
		return _bullets!=0;
	}

	public int getBullets(){
		return _bullets;
	}

	public String getType() {
		return _type;
	}

	// returns if there is another agent in its firing range
	public static boolean isKilling(int _xLocation, int _yLocation, boolean hasBullets, boolean isGhost, int x, int y, WorldMap map) {
		if (!hasBullets || isGhost) return false;
		// other agent is on same row
		if (x == _xLocation){
			if (y > _yLocation){
				// if there is a wall in the way
				for (int i = _yLocation; i<y ; i++){
					if (map.isFireBlocked(x,i)){
						return false;
					}
				}
				return true;
			} else if (y < _yLocation){
				for (int i = y; i<_yLocation ; i++){
					if (map.isFireBlocked(x,i)){
						return false;
					}
				}
				return true;
			} else return false;
		}
		// other agent is on same column
		else if (y == _yLocation){
			if (x > _xLocation){
				for (int i = _xLocation; i<x ; i++){
					if (map.isFireBlocked(i,y)){
						return false;
					}
				}
				return true;
			} else if (x < _xLocation){
				for (int i = x; i<_xLocation ; i++){
					if (map.isFireBlocked(i,y)){
						return false;
					}
				}
				return true;
			} else return false;
		} else return false;
	}
}

